package com.econvent.common.secure.utils;

import com.econvent.common.constant.RoleConstant;
import com.econvent.common.enums.constant.StringPool;
import com.econvent.common.jwt.util.JwtUtil;
import com.econvent.common.secure.EconUser;
import com.econvent.common.secure.constant.TokenConstant;
import com.econvent.common.support.Kv;
import com.econvent.common.utils.*;
import io.jsonwebtoken.Claims;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;

import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * Auth工具类
 *
 * @author xiekun
 */
public class AuthUtil {
	private static final String BLADE_USER_REQUEST_ATTR = "_BLADE_USER_REQUEST_ATTR_";

	private final static String HEADER = TokenConstant.HEADER;
	private final static String ACCOUNT = TokenConstant.ACCOUNT;
	private final static String USER_NAME = TokenConstant.USER_NAME;
	private final static String NICK_NAME = TokenConstant.NICK_NAME;
	private final static String USER_ID = TokenConstant.USER_ID;
	private final static String DEPT_ID = TokenConstant.DEPT_ID;
	private final static String POST_ID = TokenConstant.POST_ID;
	private final static String ROLE_ID = TokenConstant.ROLE_ID;
	private final static String ROLE_NAME = TokenConstant.ROLE_NAME;
	private final static String TENANT_ID = TokenConstant.TENANT_ID;
	private final static String OAUTH_ID = TokenConstant.OAUTH_ID;
	private final static String CLIENT_ID = TokenConstant.CLIENT_ID;
	private final static String CLIENTS = TokenConstant.CLIENTS;
	private final static String AUTHORITIES = TokenConstant.AUTHORITIES;
	private final static String ADDITIONAL_INFORMATION = TokenConstant.ADDITIONAL_INFORMATION;
	private final static String DETAIL = TokenConstant.DETAIL;

	/**
	 * 获取用户信息
	 *
	 * @return EconUser
	 */
	public static EconUser getUser() {
		// 获取线程变量用户信息，需手动设置
		String token = ThreadLocalUtil.get(AuthUtil.HEADER);
		if(StringUtils.isNoneEmpty(token)) {
			return getUser(token);
		}

		// 获取HttpServletRequest用户信息
		HttpServletRequest request = WebUtil.getRequest();
		if (request == null) {
			return null;
		}

		// 优先从 request 中获取
		Object econUser = request.getAttribute(BLADE_USER_REQUEST_ATTR);
		if (econUser == null) {
			econUser = getUser(request);
			if (econUser != null) {
				// 设置到 request 中
				request.setAttribute(BLADE_USER_REQUEST_ATTR, econUser);
			}
		}
		return (EconUser) econUser;
	}

	/**
	 * 获取用户信息
	 *
	 * @param request request
	 * @return EconUser
	 */
	public static EconUser getUser(HttpServletRequest request) {
		Claims claims = getClaims(request);
		if (claims == null) {
			return null;
		}
		return getUser(claims);
	}

	/**
	 * 获取用户信息
	 *
	 * @param auth auth
	 * @return EconUser
	 */
	private static EconUser getUser(String auth) {
		Claims claims = getClaims(auth);
		if (claims == null) {
			return null;
		}
		return getUser(claims);
	}

	/**
	 * 获取用户信息
	 *
	 * @param claims claims
	 * @return EconUser
	 */
	private static EconUser getUser(Claims claims) {
		String clientId = StrUtil.toStr(claims.get(AuthUtil.CLIENT_ID));
		Integer userId = NumberUtil.getIntegerValue(claims.get(AuthUtil.USER_ID));
		String tenantId = StrUtil.toStr(claims.get(AuthUtil.TENANT_ID));
		String oauthId = StrUtil.toStr(claims.get(AuthUtil.OAUTH_ID));
		String deptId = StrUtil.toStr(claims.get(AuthUtil.DEPT_ID), StringPool.MINUS_ONE);
		String postId = StrUtil.toStr(claims.get(AuthUtil.POST_ID), StringPool.MINUS_ONE);
		String roleId = StrUtil.toStr(claims.get(AuthUtil.ROLE_ID), StringPool.MINUS_ONE);
		String account = StrUtil.toStr(claims.get(AuthUtil.ACCOUNT));
		String roleName = StrUtil.toStr(claims.get(AuthUtil.ROLE_NAME));
		String userName = StrUtil.toStr(claims.get(AuthUtil.USER_NAME));
		String nickName = StrUtil.toStr(claims.get(AuthUtil.NICK_NAME));
		List<String> authorities = (List<String>) claims.get(AuthUtil.AUTHORITIES);
		Kv additionalInformation = Kv.create().setAll((Map<? extends String, ?>) claims.get(AuthUtil.ADDITIONAL_INFORMATION));
		List<String> clients = (List<String>) claims.get(AuthUtil.CLIENTS);
		Kv detail = Kv.create().setAll((Map<? extends String, ?>) claims.get(AuthUtil.DETAIL));
		EconUser econUser = new EconUser();
		econUser.setClientId(clientId);
		econUser.setUserId(userId);
		econUser.setOauthId(oauthId);
		econUser.setAccount(account);
		econUser.setDeptId(deptId);
		econUser.setPostId(postId);
		econUser.setRoleId(roleId);
		econUser.setRoleName(roleName);
		econUser.setUserName(userName);
		econUser.setNickName(nickName);
		econUser.setAuthorities(authorities);
		return econUser;
	}

	/**
	 * 是否为超管
	 *
	 * @return boolean
	 */
	public static boolean isAdministrator() {
		return StringUtils.containsAny(getUserRole(), RoleConstant.ADMINISTRATOR) || getAuthorities().contains(RoleConstant.ADMINISTRATOR);
	}

	/**
	 * 是否为管理员
	 *
	 * @return boolean
	 */
	public static boolean isAdmin() {
		return StringUtils.containsAny(getUserRole(), RoleConstant.ADMIN) ;
	}

	/**
	 * 获取用户id
	 *
	 * @return userId
	 */
	public static Integer getUserId() {
		EconUser user = getUser();
		return (null == user) ? -1 : user.getUserId();
	}

	/**
	 * 获取用户id
	 *
	 * @param request request
	 * @return userId
	 */
	public static Integer getUserId(HttpServletRequest request) {
		EconUser user = getUser(request);
		return (null == user) ? -1 : user.getUserId();
	}

	/**
	 * 获取用户账号
	 *
	 * @return userAccount
	 */
	public static String getUserAccount() {
		EconUser user = getUser();
		return (null == user) ? StringPool.EMPTY : user.getAccount();
	}

	/**
	 * 获取用户账号
	 *
	 * @param request request
	 * @return userAccount
	 */
	public static String getUserAccount(HttpServletRequest request) {
		EconUser user = getUser(request);
		return (null == user) ? StringPool.EMPTY : user.getAccount();
	}

	/**
	 * 获取用户名
	 *
	 * @return userName
	 */
	public static String getUserName() {
		EconUser user = getUser();
		return (null == user) ? StringPool.EMPTY : user.getUserName();
	}

	/**
	 * 获取用户名
	 *
	 * @param request request
	 * @return userName
	 */
	public static String getUserName(HttpServletRequest request) {
		EconUser user = getUser(request);
		return (null == user) ? StringPool.EMPTY : user.getUserName();
	}

	/**
	 * 获取昵称
	 *
	 * @return userName
	 */
	public static String getNickName() {
		EconUser user = getUser();
		return (null == user) ? StringPool.EMPTY : user.getNickName();
	}

	/**
	 * 获取昵称
	 *
	 * @param request request
	 * @return userName
	 */
	public static String getNickName(HttpServletRequest request) {
		EconUser user = getUser(request);
		return (null == user) ? StringPool.EMPTY : user.getNickName();
	}

	/**
	 * 获取用户部门
	 *
	 * @return userName
	 */
	public static String getDeptId() {
		EconUser user = getUser();
		return (null == user) ? StringPool.EMPTY : user.getDeptId();
	}

	/**
	 * 获取用户部门
	 *
	 * @param request request
	 * @return userName
	 */
	public static String getDeptId(HttpServletRequest request) {
		EconUser user = getUser(request);
		return (null == user) ? StringPool.EMPTY : user.getDeptId();
	}

	/**
	 * 获取用户岗位
	 *
	 * @return userName
	 */
	public static String getPostId() {
		EconUser user = getUser();
		return (null == user) ? StringPool.EMPTY : user.getPostId();
	}

	/**
	 * 获取用户岗位
	 *
	 * @param request request
	 * @return userName
	 */
	public static String getPostId(HttpServletRequest request) {
		EconUser user = getUser(request);
		return (null == user) ? StringPool.EMPTY : user.getPostId();
	}

	/**
	 * 获取用户角色
	 *
	 * @return userName
	 */
	public static String getUserRole() {
		EconUser user = getUser();
		return (null == user) ? StringPool.EMPTY : user.getRoleName();
	}

	/**
	 * 获取用户角色
	 *
	 * @param request request
	 * @return userName
	 */
	public static String getUserRole(HttpServletRequest request) {
		EconUser user = getUser(request);
		return (null == user) ? StringPool.EMPTY : user.getRoleName();
	}

	/**
	 * 获取用户权限
	 *
	 * @return authorities
	 */
	public static List<String> getAuthorities() {
		EconUser user = getUser();
		return (null == user) ? new ArrayList<>() : user.getAuthorities();
	}

	/**
	 * 获取第三方认证ID
	 *
	 * @return tenantId
	 */
	public static String getOauthId() {
		EconUser user = getUser();
		return (null == user) ? StringPool.EMPTY : user.getOauthId();
	}

	/**
	 * 获取第三方认证ID
	 *
	 * @param request request
	 * @return tenantId
	 */
	public static String getOauthId(HttpServletRequest request) {
		EconUser user = getUser(request);
		return (null == user) ? StringPool.EMPTY : user.getOauthId();
	}

	/**
	 * 获取客户端id
	 *
	 * @return clientId
	 */
	public static String getClientId() {
		EconUser user = getUser();
		return (null == user) ? StringPool.EMPTY : user.getClientId();
	}

	/**
	 * 获取客户端id
	 *
	 * @param request request
	 * @return clientId
	 */
	public static String getClientId(HttpServletRequest request) {
		EconUser user = getUser(request);
		return (null == user) ? StringPool.EMPTY : user.getClientId();
	}

	/**
	 * 获取用户详情
	 *
	 * @return clientId
	 */
	public static Kv getDetail() {
		EconUser user = getUser();
		return (null == user) ? Kv.create() : user.getDetail();
	}

	/**
	 * 获取用户详情
	 *
	 * @param request request
	 * @return clientId
	 */
	public static Kv getDetail(HttpServletRequest request) {
		EconUser user = getUser(request);
		return (null == user) ? Kv.create() : user.getDetail();
	}

	/**
	 * 获取Claims
	 *
	 * @param request request
	 * @return Claims
	 */
	public static Claims getClaims(HttpServletRequest request) {
		String auth = request.getHeader(AuthUtil.HEADER);
		String parameter = request.getParameter(AuthUtil.HEADER);

		Claims claims = null;
		String token;
		// 获取 Token 参数
		if (StringUtils.isNotBlank(auth)) {
			token = JwtUtil.getToken(auth);
		} else if (StringUtils.isNotBlank(parameter)) {
			token = JwtUtil.getToken(parameter);
		} else {
			String authCookie = CookieUtil.getValue(request, "accessToken");
			token = JwtUtil.getToken(authCookie);
		}

		// 获取 Token 值
		if (StringUtils.isNotBlank(token)) {
			claims = AuthUtil.parseJWT(token);
		}

		// 判断 Token 状态
		if (ObjectUtils.isNotEmpty(claims) && JwtUtil.getJwtProperties().getState()) {
			String clientId = StrUtil.toStr(claims.get(AuthUtil.CLIENT_ID));
			String tenantId = StrUtil.toStr(claims.get(AuthUtil.TENANT_ID));
			String userId = StrUtil.toStr(claims.get(AuthUtil.USER_ID));
			String accessToken = JwtUtil.getAccessToken(clientId, tenantId, userId, token);
			if (!token.equalsIgnoreCase(accessToken)) {
				return null;
			}
		}
		return claims;
	}

	/**
	 * 获取Claims
	 *
	 * @param auth auth
	 * @return Claims
	 */
	public static Claims getClaims(String auth) {
		Claims claims = null;
		String token = "";
		// 获取 Token 参数
		if (StringUtils.isNotBlank(auth)) {
			token = JwtUtil.getToken(auth);
		}

		// 获取 Token 值
		if (StringUtils.isNotBlank(token)) {
			claims = AuthUtil.parseJWT(token);
		}
		// 判断 Token 状态
		if (ObjectUtils.isNotEmpty(claims) && JwtUtil.getJwtProperties().getState()) {
			String clientId = StrUtil.toStr(claims.get(AuthUtil.CLIENT_ID));
			String tenantId = StrUtil.toStr(claims.get(AuthUtil.TENANT_ID));
			String userId = StrUtil.toStr(claims.get(AuthUtil.USER_ID));
			String accessToken = JwtUtil.getAccessToken(clientId, tenantId, userId, token);
			if (!token.equalsIgnoreCase(accessToken)) {
				return null;
			}
		}
		return claims;
	}

	/**
	 * 获取请求头
	 *
	 * @return header
	 */
	public static String getHeader() {
		return getHeader(Objects.requireNonNull(WebUtil.getRequest()));
	}

	/**
	 * 获取请求头
	 *
	 * @param request request
	 * @return header
	 */
	public static String getHeader(HttpServletRequest request) {
		return request.getHeader(HEADER);
	}

	/**
	 * 解析jsonWebToken
	 *
	 * @param jsonWebToken jsonWebToken
	 * @return Claims
	 */
	public static Claims parseJWT(String jsonWebToken) {
		return JwtUtil.parseJWT(jsonWebToken);
	}
}
